////////////////////////////////////////
//	File Header
//	Author: Stephen Ringer | stephen.ringer@gmail.com
//	File: SAGAQueue.cpp
//
////////////////////////////////////////

////////////////////////////////////////
//	File Includes
#include <stddef.h>        // #def NULL
#include <memory.h>        // memcpy()
#include "SAGAQueue.h"
//
////////////////////////////////////////

////////////////////////////////////////
//	Function Name: SAGAQueueElem
//	Purpose:
//		allocate memory and copy data in
SAGAQueueElem::SAGAQueueElem(const char *pData, unsigned int nSize) 
{
	m_pData = NULL;
	m_pNext = NULL;
	m_pData = new char[nSize];
	m_nSize = nSize;
	memcpy(m_pData, pData, nSize);
} 
//
////////////////////////////////////////

////////////////////////////////////////
//	Function Name: ~SAGAQueueElem
//	Purpose:
//		free allocated memory
SAGAQueueElem::~SAGAQueueElem() 
{
	if (m_pData) 
	{
		delete [] m_pData;
		m_pData = NULL;
	}
	m_pNext = NULL;
} 
//
////////////////////////////////////////

////////////////////////////////////////
//	Function Name: SAGAQueue
//	Purpose:
//		init pointers
SAGAQueue::SAGAQueue() 
{
	m_pTail = NULL;
	m_pHead = NULL;
	m_Count = 0;
}
//
////////////////////////////////////////

////////////////////////////////////////
//	Function Name: ~SAGAQueue
//	Purpose:
//		free all queued elements and reset members
SAGAQueue::~SAGAQueue() 
{
	while (m_pHead) Dequeue();
	m_pTail = NULL;
	m_pHead = NULL;
	m_Count = 0;
}
//
////////////////////////////////////////

////////////////////////////////////////
//	Function Name: Dequeue
//	Purpose:
//		delete the head element
void SAGAQueue::Dequeue() 
{
	SAGAQueueElem *pTemp;

	// already empty
	if (m_Count == 0) return;

	// exactly one element
	else if (m_Count == 1) 
	{
		delete m_pHead;
		m_pHead = NULL;
		m_pTail = NULL;
	}
	else 
	{
		pTemp = m_pHead;
		m_pHead = m_pHead->m_pNext;
		delete pTemp;
	}
	m_Count--;
} 
//
////////////////////////////////////////

////////////////////////////////////////
//	Function Name: Enqueue
//	Purpose:
//		put a new element in at the end of the tail.
void SAGAQueue::Enqueue(const void *pData, unsigned int nSize) 
{
	SAGAQueueElem *pNew = new SAGAQueueElem((const char*)pData, nSize);

	// this is the first package
	if (m_Count == 0) 
	{
		m_pHead = pNew;
		m_pTail = pNew;
	}
	// this is the second package
	else if(m_Count == 1) 
	{
		m_pHead->m_pNext = pNew;
		m_pTail = pNew;
	}
	else 
	{
		m_pTail->m_pNext = pNew;
		m_pTail = pNew;
	}
	m_Count++;
} 
//
////////////////////////////////////////

////////////////////////////////////////
//	Function Name: Front
//	Purpose:
//		get data from head element and delete it from queue if wished
void SAGAQueue::Front(void *pData, bool bDequeue) 
{
   if (pData) if (m_pHead) memcpy(pData, m_pHead->m_pData, m_pHead->m_nSize);
   if (bDequeue) Dequeue();
} 
//
////////////////////////////////////////